# from vb_tk import *
from Tkinter import *
import Tix
import re

def _(rstr):
    return rstr
#def _(rstr):
#    return unicode(rstr, 'gb2312')

#
## A superclass class define an interface for builders
class WidgetBuilder:
    """WidgetBuilder parent class"""
    def __init__(self, master = None):
        """Setup default options for widget"""
        self.name = 'noname'
        self.width = 0
        self.height = 0
        self.top = 0
        self.left = 0
        self.master = master
        self.obj = None
        self.factor = 15
        self.fix = 75000
        self.align = LEFT
        self.anchor = NW
        self.text = ''
        self.wobj = self.GetNew()

    def GetNew(self):
        pass

    def _todict(self, lines):
        try:
            d = dict([s.split('=') for s in lines])
        except ValueError:
            print lines
        f = {}

        for (k, v) in d.items():
            key = k.strip()
            f[key] = v.split("'")[0].strip()
            flg = f[key]
            if flg[0] == '"':
                f[key].strip('"')
            if flg[0] in '1234567890+-':
                f[key] = int(f[key])
            if flg[0] == '&':
                rr = flg[8]+flg[9]
                gg = flg[6]+flg[7]
                bb = flg[4]+flg[5]
                f[key] = "#"+rr+gg+bb
        self.cfg = f
        return f

    def SetConfig(self, lines=None):
        if lines:
            dt = self._todict(lines)
        else:
            dt = self.cfg
        keys = dt.keys()
        keys.sort()
        for k in keys:
            v = dt.__getitem__(k)
            self.next(str(k+'='+str(v)))

        if isinstance(self.master, Tix.NoteBook):
            return None
        else:
            # print self
            self.wobj = self.Finish()
            return self.wobj

    def next(self, line):
        """-> nothing. A string line as input.
        Read the line searching for and setting up
        options for the widget
        """

        # get name and value
        spline = line.split('=')

        argname = spline[0].strip()
        argval = spline[1].split("'")[0].strip()

        if argname == 'Height':
            self.height = int(argval) / self.factor
        elif argname == 'Left':
            a = int(argval)
            if a<0:
                # vb will hide sth by setting x out of left boundary
                a += self.fix

            self.left = a / self.factor

        elif argname == 'Top':
            self.top = int(argval) / self.factor
        elif argname == 'Width':
            self.width = int(argval) / self.factor
        elif argname == 'Caption':
            self.caption = _(argval.strip('"'))
        elif argname == 'ClientHeight':
            self.clheight = int(argval) / self.factor
        elif argname == 'ClientLeft':
            self.clleft = int(argval) / self.factor
        elif argname == 'ClientTop':
            self.cltop = int(argval) / self.factor
        elif argname == 'ClientWidth':
            self.clwidth = int(argval) / self.factor
        elif argname == 'Text':
            self.text = _(argval.strip('"'))
        elif argname == 'FillColor':
            self.fill = argval
        elif argname == 'BorderColor':
            self.outline = argval
        elif argname == 'Shape':
            self.shape = argval
        elif argname == 'FillStyle':
            self.fillstyle = argval
        elif argname == 'Alignment':
            if argval == '0': # left
                self.align = LEFT
                self.anchor = NW
            elif argval == '1': # right
                self.align = RIGHT
                self.anchor = NE
            elif argval == '2': # center
                self.align = CENTER
                self.anchor = N

        # call custom do_next method, over-write
        # widget's options
        self.do_next(argname, argval)

    def GetWobj(self, wbobj=None):
        return self.wobj

    def do_next(self, argname, argval):
        """for overriden"""
        pass

    def Finish(self):
        """-> widget_obj"""
        pass


#
## Default widgets' builders.

# You can add default widgets' builders here.
#
# Note:
# There's a rule for your builder's name, if
# you want vb_tk to find your builder auto-
# matically.
#
# Naming Rule for Builder:
#      class XXXBuilder(WidgetBuilder):
# It's quit simple. The only thing you have
# to know is what's the name of your widget
# for VB. For example, an Tkinter.Entry
# probably called VB.TextBox in VB, so you
# must name your builder 'TextBoxBuilder'.
# You see, the 'XXX' above is exactly the
# widget's name in VB.



class FormBuilder(WidgetBuilder):

    def do_next(self, argname, argval):
        pass
    def GetNew(self):
        self.obj = Frame(self.master)
        return self.obj

    def Finish(self):
        self.master.geometry(
                    "%dx%d+%d+%d" % (self.clwidth, self.clheight,
                    self.clleft, self.cltop)
            )
        self.master.title(self.caption)
        self.obj.place(x=0, y=0, width=self.clwidth, height=self.clheight)
        return self.obj

class CommandButtonBuilder(WidgetBuilder):
    def GetNew(self):
        self.obj = Button(self.master)
        return self.obj
    def Finish(self):
        self.obj.config(text = self.caption)
        self.obj.place(x=self.left, y=self.top,
                       width = self.width, height = self.height)
        return self.obj

class TextBoxBuilder(WidgetBuilder):
    def GetNew(self):
        self.multi = '1'
        self.sb = 'none'
        self.fcolor = 'black'
        self.obj = Tix.ScrolledText(self.master)
        return self.obj
    def do_next(self, argname, argval):
        if argname=='MultiLine':
            self.multi = argval     # -1 enable
        elif argname=='ScrollBars':
            if argval=='1':
                self.sb='auto -y'
            elif argval=='2':
                self.sb='auto -x'
            elif argval=='3':
                self.sb='both'

            # 0 none, 1 horizontal, 2 vertical, 3 both
        elif argname=='ForeColor':
            self.fcolor = argval
    def Finish(self):
        if self.multi!='-1':
            self.obj.text.bind("<Return>", lambda e: 'break')
        self.obj.config(scrollbar = self.sb)
        self.obj.text.insert(END, self.text)
        self.obj.text.config(fg=self.fcolor)
        self.obj.place(x=self.left, y=self.top, width = self.width, height = self.height)

        return self.obj


class LabelBuilder(WidgetBuilder):
    def GetNew(self):
        self.obj = Label(self.master)
        return self.obj
    def do_next(self, argname, argval):
        pass

    def Finish(self):
        #svar = StringVar(self.obj, self.caption)
        self.obj.config(anchor=self.anchor,text=self.caption)
        self.obj.place(x=self.left, y=self.top,
                         width = self.width, height = self.height)
        return self.obj

class ShapeBuilder(WidgetBuilder):
    def GetNew(self):
        self.obj = Canvas(self.master)
        return self.obj
    def do_next(self, argname, argval):
        pass

    def do_oval(self, canv):
        if self.fillstyle == '0': # solid
            color = self.fill
        elif self.fillstyle == '1': # transparent
            color = ''
        rt = canv.create_oval(2, 2,
                        self.width, self.height,
                        fill=self.fill, outline=self.outline)
        return rt

    def Finish(self):

        if self.shape == '2': # oval
            item = self.do_oval(self.obj)
            self.obj.item = item

        self.obj.place(x=self.left-1, y=self.top-1,
                     width=self.width+3, height=self.height+3)
        return self.obj

class SSTabBuilder(WidgetBuilder):

    def GetNew(self):
        self.page = {}
        self.pg = {}
        self.all = {}
        self.obj = Tix.NoteBook(self.master)
        return self.obj

    def GetWobj(self, wbobj=None):

        if wbobj:
            self.all[wbobj.name]=wbobj
        return self.obj

    def _docombine(self):
        for k,v in self.all.items():
            oldobj = v.wobj
            del oldobj

            v.master = getattr(self.obj, self.page[k])
            # print v.master, v.name

            newobj = v.GetNew()
            # copy old configure to new
            v.cfg.update({'Top':str(int(v.cfg['Top'])-self.top-30*self.factor)})
            newobj = v.SetConfig()

            setattr(v.master, v.name, newobj)

    def Finish(self):

        self._docombine()
        self.obj.place(x=self.left, y=self.top, width=self.width, height=self.height)
        return self.obj

    def do_next(self, argname, argval):

        # create new page in notebook
        # print argname
        argval = argval.strip('"')
        p = '^TabCaption\(([0-9]+)\)'
        m = re.search(p, argname)
        if m:
            self.obj.add('page'+m.groups()[0], label=argval.replace('&', '') , underline = argval.find('&'))

            return None

        # map widget to a certain page
        p = '^Tab\(([0-9]+)\).Control\('
        m = re.search(p, argname)
        if m:
            # pg = getattr(self.obj, 'page'+m.groups()[0])
            self.page[argval] = 'page'+m.groups()[0]
            return None





